package cn.wind.xboot.module.web.controller.sys;

import cn.wind.xboot.core.json.JSON;
import cn.wind.xboot.core.res.ApiResult;
import cn.wind.xboot.logic.sys.service.ISysUserService;
import cn.wind.klog.annotation.Log;
import cn.wind.klog.annotation.LogAround;
import cn.wind.klog.annotation.LogFilterType;
import cn.wind.xboot.core.utils.*;
import cn.wind.xboot.framework.captcha.LuosimaoUtil;
import cn.wind.xboot.framework.constant.ActionConstant;
import cn.wind.xboot.framework.constant.ChannelConstant;
import cn.wind.xboot.framework.constant.ModuleConstant;
import cn.wind.xboot.framework.oauth.OauthDao;
import cn.wind.xboot.module.web.handler.MyLogHandler;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>Title: LoginController</p>
 * <p>Description: TODO</p>
 *
 * @author xukk
 * @version 1.0
 * @date 2018/7/2
 */
@Controller
@RequestMapping("login")
@Api(value = "login",tags = "登录管理")
public class LoginController{

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    protected StringRedisTemplate redisTemplate;
    @Autowired
    private OauthDao oauthDao;
    @Autowired
    private ISysUserService sysUserService;
    @PostMapping
    @JSON
    @LogAround
    @Log(module = ModuleConstant.USER,action = ActionConstant.LOGIN,channel = ChannelConstant.BACK_WEB,pattern = "用户[#{#username}]登录",filterType = LogFilterType.ASPECTJ,fallback = MyLogHandler.class)
    public ApiResult signIn(HttpServletRequest request,Boolean verify, String username, String password, String grantType, @RequestHeader("Authorization") String authorization) throws Exception {
        Assert.checkArgument(verify,"请完成验证码校验");
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", AESUtil.CBC.decrypt(authorization));
        //Basic YmFja1VzZXI6YmFja1VzZXI=
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        //  也支持中文
        params.add("username", username);
        params.add("password", password);
        params.add("scope","back");
        params.add("grant_type",grantType);
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
        ResponseEntity responseEntity= restTemplate.postForEntity(RequestUtil.getBasePath(request)+"/oauth/token", requestEntity, Map.class);
        JSONObject jsonObject=JSONObject.parseObject(JsonUtil.toJson(responseEntity.getBody()));
        RSAUtil rsa = RSAUtil.build().initKeys();
        String privateKey = rsa.getPrivateKeyBase64();
        String publicKey = rsa.getPublicKeyBase64();
        redisTemplate.opsForValue().set("oauth:token:rsa:"+jsonObject.getString("access_token"),privateKey, jsonObject.getInteger("expires_in"), TimeUnit.SECONDS);
        jsonObject.put("publicKey",publicKey);
        Integer refreshExpiredTime=oauthDao.getRefreshTokenExpiredTime();
        RSAUtil rsa1 = RSAUtil.build().initKeys();
        String privateKey1 = rsa1.getPrivateKeyBase64();
        String publicKey1 = rsa1.getPublicKeyBase64();
        String refreshRandomStr=UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("oauth:token:rsa_refresh:"+refreshRandomStr,privateKey1, refreshExpiredTime, TimeUnit.SECONDS);
        jsonObject.put("refreshPublicKey",publicKey1);
        jsonObject.put("refreshRandomStr",refreshRandomStr);
        return ApiResult.Custom().success().add(jsonObject);
    }

    @PostMapping("refresh")
    @JSON
    public ApiResult refresh(HttpServletRequest request,String refreshToken, String grantType, @RequestHeader("Authorization") String authorization) throws Exception {
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", AESUtil.CBC.decrypt(authorization));
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("refresh_token",refreshToken);
        params.add("scope","back");
        params.add("grant_type", grantType);
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
        ResponseEntity responseEntity= restTemplate.postForEntity(RequestUtil.getBasePath(request)+ "/oauth/token", requestEntity, Map.class);
        JSONObject jsonObject=JSONObject.parseObject(JsonUtil.toJson(responseEntity.getBody()));
        RSAUtil rsa = RSAUtil.build().initKeys();
        String privateKey = rsa.getPrivateKeyBase64();
        String publicKey = rsa.getPublicKeyBase64();
        redisTemplate.opsForValue().set("oauth:token:rsa:"+jsonObject.getString("access_token"),privateKey, jsonObject.getInteger("expires_in"), TimeUnit.SECONDS);
        jsonObject.put("publicKey",publicKey);
        Integer refreshExpiredTime=oauthDao.getRefreshTokenExpiredTime();
        RSAUtil rsa1 = RSAUtil.build().initKeys();
        String privateKey1 = rsa1.getPrivateKeyBase64();
        String publicKey1 = rsa1.getPublicKeyBase64();
        String refreshRandomStr=UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("oauth:token:rsa_refresh:"+refreshRandomStr,privateKey1, refreshExpiredTime, TimeUnit.SECONDS);
        jsonObject.put("refreshPublicKey",publicKey1);
        jsonObject.put("refreshRandomStr",refreshRandomStr);
        return ApiResult.Custom().success().add(jsonObject);
    }
    @PostMapping("valid")
    @JSON
    public ApiResult valid(String response){
        return ApiResult.Custom(LuosimaoUtil.verify(response));
    }
}
